package at.fhooe.mcm.logic.sensors;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import at.fhooe.mcm.logic.core.Core;
import at.fhooe.mcm.logic.core.UpdateableService;
import at.fhooe.mcm.logic.event.EventManager;
import at.fhooe.mcm.logic.logging.ConsoleLoggingService;

public class SensorManager implements UpdateableService
{

	public static final String	NAME			= "core.sensormanager";

	private Map<String, Sensor>	m_sensors		= new HashMap<String, Sensor>();
	private List<Sensor>		m_newSensors	= new ArrayList<Sensor>();
	private List<Sensor>		m_oldSensors	= new ArrayList<Sensor>();
	private List<Sensor>		m_activeSensors	= new ArrayList<Sensor>();
	private ConsoleLoggingService		m_logger;

	@Override
	public String getName()
	{
		return NAME;
	}

	@Override
	public void initialize(Core _core)
	{
		EventManager.getInstance(_core);
		m_logger = ConsoleLoggingService.getInstance(_core);
	}

	@Override
	public void update()
	{
		// engage new entities
		for (Iterator<Sensor> it = m_newSensors.iterator(); it.hasNext();)
		{
			Sensor entity = it.next();
			engageEntity(entity);
		}

		m_newSensors.clear();

		// disengage and remove old entities
		for (Iterator<Sensor> it = m_oldSensors.iterator(); it.hasNext();)
		{
			Sensor entity = it.next();
			disengageEntity(entity);
			m_sensors.remove(entity.getID());
		}

		m_oldSensors.clear();
	}

	public void pull()
	{
		// update entities
		for (Iterator<Sensor> it = m_activeSensors.iterator(); it.hasNext();)
		{
			Sensor s = it.next();

			if (!s.isPushingService())
				s.update();
		}
	}

	private void engageEntity(Sensor _entity)
	{
		_entity.engage();
		m_activeSensors.add(_entity);
		m_logger.logDebug("EntityManager", "entity '" + _entity.getID() + "' engaged");
	}

	private void disengageEntity(Sensor _entity)
	{
		m_activeSensors.remove(_entity);
		_entity.disengage();
		m_logger.logDebug("EntityManager", "entity '" + _entity.getID() + "' disengaged");
	}

	public static SensorManager getInstance(Core _core)
	{
		return (SensorManager) _core.getService(NAME);
	}

	public void addEntity(Sensor _entity)
	{
		Sensor oldEntity = m_sensors.put(_entity.getID(), _entity);
		if (oldEntity != null)
		{
			m_sensors.put(oldEntity.getID(), oldEntity);
			throw new RuntimeException("entity with name '" + _entity.getID() + "' already exists");
		}

		m_newSensors.add(_entity);
	}

	public void removeEntity(Sensor _entity)
	{
		removeEntity(_entity.getID());
	}

	public void removeEntity(String _name)
	{
		Sensor entity = getEntity(_name);
		if (!m_oldSensors.contains(entity))
		{
			m_oldSensors.add(getEntity(_name));
		}
	}

	public boolean hasEntity(String _name)
	{
		return m_sensors.containsKey(_name);
	}

	public Sensor getEntity(String _name)
	{
		Sensor entity = m_sensors.get(_name);

		if (entity == null)
		{
			throw new RuntimeException("entity with name '" + _name + "' not found");
		}

		return entity;
	}

	public Hashtable<String, String> getPublicSensorList()
	{
		Hashtable<String, String> temp = new Hashtable<String, String>();

		for (Iterator<Sensor> it = m_sensors.values().iterator(); it.hasNext();)
		{
			Sensor s = it.next();

			if (s.isPublic()){
				StringBuffer sb = new StringBuffer(s.getType());
				sb.append(";");
				sb.append(s.getSensorName());
				
			
				temp.put(s.getID(), sb.toString());
			}
		}

		return temp;
	}
	
	public ArrayList<Sensor> getAllSensors()
	{
		ArrayList<Sensor> temp = new ArrayList<Sensor>();
		
		for (Iterator<Sensor> it = m_sensors.values().iterator(); it.hasNext();)
		{
			temp.add(it.next());
		}
		return temp;
	}

	public void removeAllEntities()
	{
		for (Iterator<Sensor> it = m_sensors.values().iterator(); it.hasNext();)
		{
			removeEntity(it.next());
		}
	}

	public int numOfEntities()
	{
		return m_sensors.size();
	}

	public Iterator<Sensor> engagedEntitiesIterator()
	{
		return m_activeSensors.iterator();
	}

	@Override
	public void shutdown(Core core)
	{
		// TODO Auto-generated method stub
		
	}
}
